package com.nanhai.buddhist.college.module.system.service.auth;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Lists;
import com.nanhai.buddhist.college.framework.common.enums.CommonStatusEnum;
import com.nanhai.buddhist.college.framework.common.enums.UserTypeEnum;
import com.nanhai.buddhist.college.framework.common.pojo.CommonResult;
import com.nanhai.buddhist.college.framework.common.util.collection.CollectionUtils;
import com.nanhai.buddhist.college.framework.common.util.json.JsonUtils;
import com.nanhai.buddhist.college.framework.common.util.monitor.TracerUtils;
import com.nanhai.buddhist.college.framework.common.util.servlet.ServletUtils;
import com.nanhai.buddhist.college.framework.common.util.validation.ValidationUtils;
import com.nanhai.buddhist.college.module.collegebase.api.college.CollegeApi;
import com.nanhai.buddhist.college.module.collegebase.api.college.dto.CollegesRespDTO;
import com.nanhai.buddhist.college.module.collegebase.api.collegeclass.CollegeClassApi;
import com.nanhai.buddhist.college.module.collegebase.api.collegeclass.dto.ClassesBaseInfoDTO;
import com.nanhai.buddhist.college.module.collegebase.api.student.StudentApi;
import com.nanhai.buddhist.college.module.collegebase.api.student.dto.StudentRespDTO;
import com.nanhai.buddhist.college.module.collegebase.api.student.dto.StudentUserRespDTO;
import com.nanhai.buddhist.college.module.collegebase.api.teacher.TeacherApi;
import com.nanhai.buddhist.college.module.collegebase.api.teacher.dto.TeacherRespDTO;
import com.nanhai.buddhist.college.module.collegebase.api.teacher.dto.TeacherUserRespDTO;
import com.nanhai.buddhist.college.module.system.api.logger.dto.LoginLogCreateReqDTO;
import com.nanhai.buddhist.college.module.system.api.sms.SmsCodeApi;
import com.nanhai.buddhist.college.module.system.api.social.dto.SocialUserBindReqDTO;
import com.nanhai.buddhist.college.module.system.controller.admin.auth.vo.*;
import com.nanhai.buddhist.college.module.system.convert.auth.AuthConvert;
import com.nanhai.buddhist.college.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import com.nanhai.buddhist.college.module.system.dal.dataobject.permission.RoleDO;
import com.nanhai.buddhist.college.module.system.dal.dataobject.social.SocialUserBindDO;
import com.nanhai.buddhist.college.module.system.dal.dataobject.user.AdminUserDO;
import com.nanhai.buddhist.college.module.system.enums.logger.LoginLogTypeEnum;
import com.nanhai.buddhist.college.module.system.enums.logger.LoginResultEnum;
import com.nanhai.buddhist.college.module.system.enums.oauth2.OAuth2ClientConstants;
import com.nanhai.buddhist.college.module.system.enums.sms.SmsSceneEnum;
import com.nanhai.buddhist.college.module.system.service.common.CaptchaService;
import com.nanhai.buddhist.college.module.system.service.logger.LoginLogService;
import com.nanhai.buddhist.college.module.system.service.oauth2.OAuth2TokenService;
import com.nanhai.buddhist.college.module.system.service.permission.PermissionService;
import com.nanhai.buddhist.college.module.system.service.permission.RoleService;
import com.nanhai.buddhist.college.module.system.service.social.SocialUserService;
import com.nanhai.buddhist.college.module.system.service.user.AdminUserService;
import com.google.common.annotations.VisibleForTesting;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.Validator;
import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

import static com.nanhai.buddhist.college.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.nanhai.buddhist.college.framework.common.util.servlet.ServletUtils.getClientIP;
import static com.nanhai.buddhist.college.module.system.enums.ErrorCodeConstants.*;
import static java.util.Collections.singleton;

/**
 * Auth Service 实现类
 *
 * @author 开发
 */
@Service
@Slf4j
public class AdminAuthServiceImpl implements AdminAuthService {

    public static final String ALL = "all";
    public static final String CLASS = "class";
    @Resource
    private AdminUserService userService;
    @Resource
    private CaptchaService captchaService;
    @Resource
    private LoginLogService loginLogService;
    @Resource
    private OAuth2TokenService oauth2TokenService;
    @Resource
    private SocialUserService socialUserService;

    @Resource
    private Validator validator;

    @Resource
    private SmsCodeApi smsCodeApi;


    @Resource
    private TeacherApi teacherApi;


    @Resource
    private StudentApi studentApi;

    @Resource
    private CollegeClassApi collegeClassApi;

    @Resource
    private CollegeApi collegeApi;

    @Resource
    private RoleService roleService;

    @Resource
    private PermissionService permissionService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public AuthUserRespVo authenticate(String username, String password) {
        final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_USERNAME;

        CommonResult<StudentUserRespDTO> studentByUserName = studentApi.getStudentByUserName(username);
        String studentId = Optional.ofNullable(studentByUserName).map(CommonResult::getData).map(StudentUserRespDTO::getStudentId).orElse(null);


        if (StringUtils.isNotBlank(studentId)) {
            if (!userService.isPasswordMatch(password, studentByUserName.getData().getPassword())) {
                createLoginLog(studentId, username, UserTypeEnum.STUDENT.getValue(), logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
                throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
            }

            AuthUserRespVo build = AuthUserRespVo.builder().userId(studentId).userType(UserTypeEnum.STUDENT.getValue()).username(username).build();
            return build;
        }


//        CommonResult<TeacherUserRespDTO> teacherByUserName = teacherApi.getTeacherByUserName(username);
//        String teacherId = Optional.ofNullable(teacherByUserName).map(CommonResult::getData).map(TeacherUserRespDTO::getTeacherId).orElse(null);
//
//
//        if (StringUtils.isNotBlank(teacherId)) {
//
//            if (!userService.isPasswordMatch(password, teacherByUserName.getData().getPassword())) {
//                createLoginLog(studentId, username, UserTypeEnum.TEACHER.getValue(), logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
//                throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
//            }
//
//            AuthUserRespVo build = AuthUserRespVo.builder().userId(teacherId).userType(UserTypeEnum.TEACHER.getValue()).username(username).build();
//            return build;
//        }


        // 校验账号是否存在
        AdminUserDO user = userService.getUserByUsername(username);
        if (user == null) {
            createLoginLog(null, username, UserTypeEnum.ADMIN.getValue(), logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
            throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
        }
        if (!userService.isPasswordMatch(password, user.getPassword())) {
            createLoginLog(user.getId(), username, UserTypeEnum.ADMIN.getValue(), logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
            throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
        }
        // 校验是否禁用
        if (ObjectUtil.notEqual(user.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
            createLoginLog(user.getId(), username, UserTypeEnum.ADMIN.getValue(), logTypeEnum, LoginResultEnum.USER_DISABLED);
            throw exception(AUTH_LOGIN_USER_DISABLED);
        }


        AuthUserRespVo build2 = AuthUserRespVo.builder().userId(user.getId()).userType(UserTypeEnum.ADMIN.getValue()).username(username).build();
        if (isOnlyTeacher(user.getId())) {
            build2 = AuthUserRespVo.builder().userId(user.getId()).userType(UserTypeEnum.TEACHER.getValue()).username(username).build();
        }

        if (UserTypeEnum.ADMIN.getValue().equals(build2.getUserType())) {
            initData(user.getPermissionJson(), build2.getUserId());
        }
        return build2;

    }


    private boolean isOnlyTeacher(String userId) {
        Set<Long> userRoleIdListByUserId = permissionService.getUserRoleIdListByUserId(userId);
        if (userRoleIdListByUserId != null && userRoleIdListByUserId.size() == 1 && userRoleIdListByUserId.toArray()[0].equals(3L)) {
            return true;
        }
        return false;
    }


    private void initData(String permissionJson, String userId) {


        Set<Long> roleIds = permissionService.getUserRoleIdsFromCache(userId, singleton(CommonStatusEnum.ENABLE.getStatus()));
        if (CollUtil.isEmpty(roleIds)) {
            return;
        }
        // 判断是否是超管。如果是，当然符合条件
        boolean flag_admin = false;
        List<RoleDO> roleList = roleService.getRolesFromCache(roleIds);
        if (roleService.hasAnyAdmin(roleList)) {
            flag_admin = true;
        }

        Set<String> collegeId = new HashSet<>();
        Set<String> departmentIds = new HashSet<>();
        Set<String> professionIds = new HashSet<>();
        Set<String> classesIds = new HashSet<>();
        if (StringUtils.startsWith(permissionJson, "\"")) {
            permissionJson = StringUtils.replace(permissionJson, "\\", "");
            permissionJson = StringUtils.substring(permissionJson, 1, permissionJson.length() - 1);
        }
        Map<String, Object> userPermissionListVo = JsonUtils.parseObject(permissionJson, Map.class);
        if (userPermissionListVo == null) {
//            userPermissionListVo = new UserPermissionListVo();
            userPermissionListVo = new HashMap<>();
            userPermissionListVo.put(ALL, true);


        }


        if (flag_admin) {
            userPermissionListVo.put(ALL, true);
        }

        Boolean bool = MapUtil.getBool(userPermissionListVo, ALL, false);


        if (bool) {
            CommonResult<List<CollegesRespDTO>> collegesAll = collegeApi.getCollegesAll();
            collegeId.addAll(CollectionUtils.convertSet(collegesAll.getData(), CollegesRespDTO::getId));
        } else {

            collegeId.addAll(userPermissionListVo.keySet());
        }

        collegeId.remove(ALL);


        CommonResult<List<ClassesBaseInfoDTO>> classesInfoDTOByCollegeIds = collegeClassApi.selectClassBaseInfoByCollegeIds(collegeId);
        List<ClassesBaseInfoDTO> data = classesInfoDTOByCollegeIds.getData();

        ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
        if (StringUtils.isBlank(permissionJson) || flag_admin) {
            collegeId.addAll(data.stream().map(ClassesBaseInfoDTO::getCollegeId).filter(Objects::nonNull).collect(Collectors.toSet()));
            departmentIds.addAll(data.stream().map(ClassesBaseInfoDTO::getDepartmentsId).filter(Objects::nonNull).collect(Collectors.toSet()));
            professionIds.addAll(data.stream().map(ClassesBaseInfoDTO::getProfessionsId).filter(Objects::nonNull).collect(Collectors.toSet()));
            classesIds.addAll(data.stream().map(ClassesBaseInfoDTO::getClassesId).filter(Objects::nonNull).collect(Collectors.toSet()));

            stringStringValueOperations.set("user_data_" + userId, System.currentTimeMillis() + "", Duration.ofDays(30));
            stringStringValueOperations.set("user_collegeIds_" + userId, JsonUtils.toJsonString(collegeId), Duration.ofDays(30));
            stringStringValueOperations.set("user_departmentIds_" + userId, JsonUtils.toJsonString(departmentIds), Duration.ofDays(30));
            stringStringValueOperations.set("user_professionIds_" + userId, JsonUtils.toJsonString(professionIds), Duration.ofDays(30));
            stringStringValueOperations.set("user_classesIds_" + userId, JsonUtils.toJsonString(classesIds), Duration.ofDays(30));
            return;
        } else if (StringUtils.isBlank(permissionJson)) {
            stringStringValueOperations.set("user_data_" + userId, System.currentTimeMillis() + "", Duration.ofDays(30));
            stringStringValueOperations.set("user_collegeIds_" + userId, JsonUtils.toJsonString(collegeId), Duration.ofDays(30));
            stringStringValueOperations.set("user_departmentIds_" + userId, JsonUtils.toJsonString(departmentIds), Duration.ofDays(30));
            stringStringValueOperations.set("user_professionIds_" + userId, JsonUtils.toJsonString(professionIds), Duration.ofDays(30));
            stringStringValueOperations.set("user_classesIds_" + userId, JsonUtils.toJsonString(classesIds), Duration.ofDays(30));
            return;
        }

        // 遍历学院ID
        Map<String, Object> finalUserPermissionListVo = userPermissionListVo;
        HashMap<String, Object> singe_colleges = MapUtil.newHashMap();
        collegeId.stream().forEach(collegeId_p -> {
            if (ALL.equals(collegeId_p)) {
                singe_colleges.put(ALL, finalUserPermissionListVo.get(ALL));
                return;
            }

            Map o = MapUtil.get(finalUserPermissionListVo, collegeId_p, Map.class);
            if (Objects.isNull(o) || o.isEmpty()) {
                o = new HashMap();
                o.put(ALL, true);
            }
            // 如果学院下的系部 all=true ， 获取所有学院的系
            if (MapUtil.getBool(o, ALL, false)) {
                departmentIds.addAll(data.stream().filter(t -> StringUtils.equals(collegeId_p, t.getCollegeId()) && Objects.nonNull(t.getDepartmentsId())).map(ClassesBaseInfoDTO::getDepartmentsId).collect(Collectors.toSet()));
            } else {
                departmentIds.addAll(o.keySet());
            }

            // 遍历系部ID
            Map<String, Object> finalO = o;
            HashMap<String, Object> singe_departments = MapUtil.newHashMap();
            finalO.keySet().forEach(department_id_p -> {

                if (ALL.equals(department_id_p)) {
                    singe_departments.put(ALL, finalO.get(ALL));
                    return;
                }


                Map map = MapUtil.get(finalO, department_id_p, Map.class);
                if (Objects.isNull(map)) {
                    map = new HashMap();
                    map.put(ALL, true);
                }
                if (MapUtil.getBool(map, ALL, false)) {
                    professionIds.addAll(data.stream().filter(t -> StringUtils.equals(department_id_p, t.getDepartmentsId()) && Objects.nonNull(t.getProfessionsId())).map(ClassesBaseInfoDTO::getProfessionsId).collect(Collectors.toSet()));
                } else {
                    professionIds.addAll(map.keySet());
                }
                // 遍历专业ID
                Map<String, Object> finalMap = map;
                HashMap<String, Object> singe_profession = MapUtil.newHashMap();
                finalMap.keySet().forEach(professionIds_p -> {
                    if (ALL.equals(professionIds_p)) {
                        singe_profession.put(ALL, finalMap.get(ALL));
                        return;
                    }

                    Map classesMap = MapUtil.get(finalMap, professionIds_p, Map.class);
                    if (Objects.isNull(classesMap)) {
                        classesMap = new HashMap();
                        classesMap.put(ALL, true);
                    }
                    List<String> classes_ids = Lists.newArrayList();
                    if (MapUtil.getBool(classesMap, ALL, false)) {
                        classes_ids = data.stream().filter(t -> StringUtils.equals(professionIds_p, t.getProfessionsId()) && Objects.nonNull(t.getClassesId())).map(ClassesBaseInfoDTO::getClassesId).collect(Collectors.toList());
                    } else {
                        classes_ids = MapUtil.get(classesMap, CLASS, List.class, Lists.newArrayList());
                    }
                    classesIds.addAll(classes_ids);
                    singe_profession.put("class", classes_ids);
                });


                singe_departments.put(department_id_p, singe_profession);

            });

            singe_colleges.put(collegeId_p, singe_departments);
        });

        System.out.println(JsonUtils.toJsonString(singe_colleges));


        departmentIds.remove(ALL);
        professionIds.remove(ALL);
        classesIds.remove(ALL);


        stringStringValueOperations.set("user_data_" + userId, System.currentTimeMillis() + "", Duration.ofDays(30));
        stringStringValueOperations.set("user_collegeIds_" + userId, JsonUtils.toJsonString(collegeId), Duration.ofDays(30));
        stringStringValueOperations.set("user_departmentIds_" + userId, JsonUtils.toJsonString(departmentIds), Duration.ofDays(30));
        stringStringValueOperations.set("user_professionIds_" + userId, JsonUtils.toJsonString(professionIds), Duration.ofDays(30));
        stringStringValueOperations.set("user_classesIds_" + userId, JsonUtils.toJsonString(classesIds), Duration.ofDays(30));


    }

    @Override
    public AuthLoginRespVO login(AuthLoginReqVO reqVO) {
        // 判断验证码是否正确
        verifyCaptcha(reqVO);

        // 使用账号密码，进行登录
        AuthUserRespVo user = authenticate(reqVO.getUsername(), reqVO.getPassword());

        // 如果 socialType 非空，说明需要绑定社交用户
        if (reqVO.getSocialType() != null) {
            socialUserService.bindSocialUser(new SocialUserBindReqDTO(user.getUserId(), user.getUserType(),
                    reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState()));
        }

        // 创建 Token 令牌，记录登录日志
        return createTokenAfterLoginSuccess(user.getUserId(), reqVO.getUsername(), user.getUserType(), LoginLogTypeEnum.LOGIN_USERNAME);
    }

    @Override
    public void sendSmsCode(AuthSmsSendReqVO reqVO) {
        // 登录场景，验证是否存在
        if (userService.getUserByMobile(reqVO.getMobile()) == null) {
            throw exception(AUTH_MOBILE_NOT_EXISTS);
        }
        // 发送验证码
        smsCodeApi.sendSmsCode(AuthConvert.INSTANCE.convert(reqVO).setCreateIp(getClientIP()));
    }

    @Override
    public AuthLoginRespVO smsLogin(AuthSmsLoginReqVO reqVO) {
        // 校验验证码
        smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.ADMIN_MEMBER_LOGIN.getScene(), getClientIP()));

        // 获得用户信息
        AdminUserDO user = userService.getUserByMobile(reqVO.getMobile());
        if (user == null) {
            throw exception(USER_NOT_EXISTS);
        }

        // 创建 Token 令牌，记录登录日志
        return createTokenAfterLoginSuccess(user.getId(), reqVO.getMobile(), UserTypeEnum.ADMIN.getValue(), LoginLogTypeEnum.LOGIN_MOBILE);
    }

    @VisibleForTesting
    void verifyCaptcha(AuthLoginReqVO reqVO) {
        // 如果验证码关闭，则不进行校验
        if (!captchaService.isCaptchaEnable()) {
            return;
        }
        // 校验验证码
        ValidationUtils.validate(validator, reqVO, AuthLoginReqVO.CodeEnableGroup.class);
        // 验证码不存在
        final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_USERNAME;
        String code = captchaService.getCaptchaCode(reqVO.getUuid());
        if (code == null) {
            // 创建登录失败日志（验证码不存在）
            createLoginLog(null, reqVO.getUsername(), UserTypeEnum.ADMIN.getValue(), logTypeEnum, LoginResultEnum.CAPTCHA_NOT_FOUND);
            throw exception(AUTH_LOGIN_CAPTCHA_NOT_FOUND);
        }
        // 验证码不正确
        if (!code.equals(reqVO.getCode())) {
            // 创建登录失败日志（验证码不正确)
            createLoginLog(null, reqVO.getUsername(), UserTypeEnum.ADMIN.getValue(), logTypeEnum, LoginResultEnum.CAPTCHA_CODE_ERROR);
            throw exception(AUTH_LOGIN_CAPTCHA_CODE_ERROR);
        }
        // 正确，所以要删除下验证码
        captchaService.deleteCaptchaCode(reqVO.getUuid());
    }

    private void createLoginLog(String userId, String username, Integer userType,
                                LoginLogTypeEnum logTypeEnum, LoginResultEnum loginResult) {
        // 插入登录日志
        LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO();
        reqDTO.setLogType(logTypeEnum.getType());
        reqDTO.setTraceId(TracerUtils.getTraceId());
        reqDTO.setUserId(userId);
        reqDTO.setUserType(userType);
        reqDTO.setUsername(username);
        reqDTO.setUserAgent(ServletUtils.getUserAgent());
        reqDTO.setUserIp(ServletUtils.getClientIP());
        reqDTO.setResult(loginResult.getResult());
        loginLogService.createLoginLog(reqDTO);
        // 更新最后登录时间
        if (userId != null && Objects.equals(LoginResultEnum.SUCCESS.getResult(), loginResult.getResult())) {
            userService.updateUserLogin(userId, ServletUtils.getClientIP());
        }
    }

    @Override
    public AuthLoginRespVO socialLogin(AuthSocialLoginReqVO reqVO) {
        // 使用 code 授权码，进行登录。然后，获得到绑定的用户编号
        SocialUserBindDO socialUserBindDO = socialUserService.getBindUserId(reqVO.getType(),
                reqVO.getCode(), reqVO.getState());
        if (Objects.isNull(socialUserBindDO) || socialUserBindDO.getUserId() == null) {
            throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
        }

        // 获得用户 todo
//        AdminUserDO user = userService.getUser(userId);
//        if (user == null) {
//            throw exception(USER_NOT_EXISTS);
//        }

        // 创建 Token 令牌，记录登录日志
        return createTokenAfterLoginSuccess(socialUserBindDO.getUserId(), "社交用户登陆", socialUserBindDO.getUserType(), LoginLogTypeEnum.LOGIN_SOCIAL);
    }

    @Override
    public AuthLoginRespVO refreshToken(String refreshToken) {
        OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, OAuth2ClientConstants.CLIENT_ID_DEFAULT);
        return AuthConvert.INSTANCE.convert(accessTokenDO);
    }

    @Override
    public UserVO getUserInfo(String userId, UserTypeEnum userTypeEnum) {
        if (userTypeEnum.equals(UserTypeEnum.ADMIN)) {
            AdminUserDO user = userService.getUser(userId);
            return UserVO.builder().id(userId).nickname(user.getNickname()).avatar(user.getAvatar()).build();
        } else if (userTypeEnum.equals(UserTypeEnum.TEACHER)) {
            CommonResult<TeacherRespDTO> teacherList = teacherApi.getTeacherById(userId);
            String avatar = Optional.ofNullable(teacherList).map(CommonResult::getData).map(TeacherRespDTO::getHeadImage).orElse("");
            String nickname = Optional.ofNullable(teacherList).map(CommonResult::getData).map(TeacherRespDTO::getTeacherName).orElse("");
            return UserVO.builder().id(userId)
                    .avatar(avatar).nickname(nickname).build();
        } else if (userTypeEnum.equals(UserTypeEnum.STUDENT)) {
            CommonResult<StudentRespDTO> studentRespDTOById = studentApi.getStudentRespDTOById(userId);
            String avatar = Optional.ofNullable(studentRespDTOById).map(CommonResult::getData).map(StudentRespDTO::getHeadImage).orElse("");
            String nickname = Optional.ofNullable(studentRespDTOById).map(CommonResult::getData).map(StudentRespDTO::getStudentName).orElse("");
            return UserVO.builder().id(userId)
                    .avatar(avatar).nickname(nickname).build();
        }
        return null;
    }

    private AuthLoginRespVO createTokenAfterLoginSuccess(String userId, String username, Integer userType, LoginLogTypeEnum logType) {
        // 插入登陆日志
        createLoginLog(userId, username, userType, logType, LoginResultEnum.SUCCESS);
        // 创建访问令牌
        OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(userId, userType,
                OAuth2ClientConstants.CLIENT_ID_DEFAULT, null);
        // 构建返回结果
        return AuthConvert.INSTANCE.convert(accessTokenDO);
    }

    @Override
    public void logout(String token, Integer logType) {
        // 删除访问令牌
        OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.removeAccessToken(token);
        if (accessTokenDO == null) {
            return;
        }
        // 删除成功，则记录登出日志
        createLogoutLog(accessTokenDO.getUserId(), accessTokenDO.getUserType(), logType);
    }

    private void createLogoutLog(String userId, Integer userType, Integer logType) {
        LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO();
        reqDTO.setLogType(logType);
        reqDTO.setTraceId(TracerUtils.getTraceId());
        reqDTO.setUserId(userId);
        reqDTO.setUserType(userType);

        reqDTO.setUsername("用户退出");

        reqDTO.setUserAgent(ServletUtils.getUserAgent());
        reqDTO.setUserIp(ServletUtils.getClientIP());
        reqDTO.setResult(LoginResultEnum.SUCCESS.getResult());
        loginLogService.createLoginLog(reqDTO);
    }

    private String getUsername(String userId) {
        if (userId == null) {
            return null;
        }
        AdminUserDO user = userService.getUser(userId);
        return user != null ? user.getUsername() : null;
    }

//    private UserTypeEnum getUserType() {
//        return UserTypeEnum.ADMIN;
//    }


    @Override
    public void initUserCollegeData(String userId) {

        AdminUserDO user = userService.getUser(userId);
        this.initData(user.getPermissionJson(), userId);

    }

    @Override
    public void saveUserCollegeData(String userId, Integer type, String parentId, String id) {
        AdminUserDO user = userService.getUser(userId);


        Set<Long> roleIds = permissionService.getUserRoleIdsFromCache(userId, singleton(CommonStatusEnum.ENABLE.getStatus()));
        if (CollUtil.isEmpty(roleIds)) {
            return;
        }
        // 判断是否是超管。如果是，当然符合条件
        boolean flag_admin = false;
        List<RoleDO> roleList = roleService.getRolesFromCache(roleIds);
        if (roleService.hasAnyAdmin(roleList)) {
            flag_admin = true;
        }

        if (flag_admin) {
            return;
        }

        String permissionJson = user.getPermissionJson();

        if (StringUtils.isNotBlank(permissionJson)) {
            if (StringUtils.startsWith(permissionJson, "\"")) {
                permissionJson = StringUtils.replace(permissionJson, "\\", "");
                permissionJson = StringUtils.substring(permissionJson, 1, permissionJson.length() - 1);
            }
            if (0 == type) {
                Map<String, Object> userPermissionListVo = JsonUtils.parseObject(permissionJson, Map.class);
                userPermissionListVo.put(id, new HashMap<String, Object>());
                String s1 = JsonUtils.toJsonString(userPermissionListVo);
                userService.updateUserPermission(userId, s1);
            }

            if (1 == type) {
                Map<String, Object> userPermissionListVo = JsonUtils.parseObject(permissionJson, Map.class);

                Map<String, Object> departmentMap = MapUtil.get(userPermissionListVo, parentId, Map.class);
                departmentMap.put(id, new HashMap<String, Object>());
                userPermissionListVo.put(parentId, departmentMap);
                String s = JsonUtils.toJsonString(userPermissionListVo);
                userService.updateUserPermission(userId, s);
            }


            if (2 == type) {
                Map<String, Object> userPermissionListVo = JsonUtils.parseObject(permissionJson, Map.class);

                for (String s : userPermissionListVo.keySet()) {
                    if (!ALL.equals(s)) {
                        Map<String, Object> map = MapUtil.get(userPermissionListVo, s, Map.class);

                        if (map.keySet().contains(parentId)) {
                            Map<String, Object> map1 = MapUtil.get(map, parentId, Map.class);
                            HashMap<String, Object> objectObjectHashMap = MapUtil.newHashMap();
                            objectObjectHashMap.put(ALL, true);
                            map1.put(id, objectObjectHashMap);

                            map.put(parentId, map1);
                        }
                        userPermissionListVo.put(s, map);
                    } else {
                        userPermissionListVo.put(s, MapUtil.get(userPermissionListVo, s, Boolean.class));
                    }

                }


                userService.updateUserPermission(userId, JsonUtils.toJsonString(userPermissionListVo));
            }

        }


    }

    @Override
    public Boolean checkRoleUser(String id) {
        return userService.checkRoleUser(id);
    }
}
